package com.z.system.service.impl;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.z.system.exception.BusinessException;
import com.z.system.model.Permission;
import com.z.system.model.User;
import com.z.system.repository.PermissionRepository;
import com.z.system.service.PermissionService;
import com.z.system.service.UserService;
import com.z.system.vo.Menu;

import io.micrometer.common.util.StringUtils;

/**
 * 权限服务实现类
 */
@Service
public class PermissionServiceImpl implements PermissionService {

    @Autowired
    private PermissionRepository permissionRepository;

    @Override
    public Permission getPermissionById(UUID id) {
        return permissionRepository.findById(id).orElse(null);
    }

    @Override
    public Permission getPermissionByPermission(String permission) {
        return permissionRepository.findByPermission(permission);
    }

    @Override
    public List<Permission> getAllPermissions() {
        // 此处保留原方法签名，但在实际调用中会通过另一个方法获取转换后的Menu对象
        return permissionRepository.findAll();
    }

    /**
     * 获取所有权限并转换为前端友好的菜单树结构
     * 与getCurrentUserMenus返回相同格式的数据
     * 
     * @return 菜单树结构列表
     */
    @Override
    public List<Menu> getAllPermissionsAsMenuTree() {
        // 从数据库获取所有权限
        List<Permission> allPermissions = permissionRepository.findAll();
        // 构建父ID到子权限列表的映射，使用HashMap允许null键
        Map<UUID, List<Permission>> parentIdToPermissionsMap = allPermissions.stream()
                .filter(permission -> permission.getType() == 2) // 查找按钮权限
                .collect(Collectors.groupingBy(Permission::getParentId));

        // 过滤出菜单类型的权限（type=0：模块，type=1：页面）转换为menu对象
        List<Menu> menuList = allPermissions.stream()
                .filter(permission -> permission.getType() == 0 || permission.getType() == 1)
                .sorted(Comparator.comparing(Permission::getSort, Comparator.nullsLast(Integer::compareTo)))
                .map(permission -> convertToMenu(permission, parentIdToPermissionsMap))
                .collect(Collectors.toList());

        // 将权限数据转换为菜单树结构
        return buildMenuTreeRecursive(menuList);
    }

    @Override
    public List<Permission> getPermissionsByRoleId(UUID roleId) {
        return permissionRepository.findByRoleId(roleId);
    }

    @Override
    public Permission savePermission(Permission permission) {
        // 检查权限标识是否已存在
        if (permissionRepository.existsByPermission(permission.getPermission())) {
            throw new BusinessException("权限标识已存在");
        }
        // 设置创建时间
        if (permission.getCreateTime() == null) {
            permission.setCreateTime(new Date());
            permission.setCreateId(userService.getCurrentUser().getId().toString());
        }
        return permissionRepository.save(permission);
    }

    @Override
    public Permission updatePermission(Permission permission) {
        Permission existingPermission = permissionRepository.findById(permission.getId())
                .orElseThrow(() -> new BusinessException("权限不存在"));

        // 检查权限标识是否已存在（排除当前权限）
        if (StringUtils.isNotEmpty(existingPermission.getPermission()) &&
                !existingPermission.getPermission().equals(permission.getPermission()) &&
                permissionRepository.existsByPermission(permission.getPermission())) {
            throw new BusinessException("权限标识已存在");
        }
        // 将前端非空值copy到数据对象
        BeanUtils.copyProperties(permission, existingPermission, "type", "createTime", "createId", "id");
        // 设置更新时间
        existingPermission.setUpdateTime(new Date());
        existingPermission.setUpdateId(userService.getCurrentUser().getId().toString());

        return permissionRepository.save(existingPermission);
    }

    @Override
    public void deletePermission(UUID id) {
        Permission permission = permissionRepository.findById(id)
                .orElseThrow(() -> new BusinessException("权限不存在"));
        // 检查权限是否被角色使用
        // 简化实现，直接删除
        permissionRepository.delete(permission);
    }

    @Override
    public void deletePermissions(Set<UUID> ids) {
        List<Permission> permissions = permissionRepository.findAllById(ids);
        if (permissions.size() != ids.size()) {
            throw new RuntimeException("部分权限不存在");
        }
        // 检查权限是否被角色使用
        // 简化实现，直接删除
        permissionRepository.deleteAll(permissions);
    }

    @Autowired
    private UserService userService;

    @Override
    public List<Menu> getCurrentUserMenus() {
        // 获取当前登录用户
        User currentUser = userService.getCurrentUser();
        if (currentUser == null) {
            // 如果用户未登录或principal不是User类型，返回空菜单列表
            return new ArrayList<>();
        }

        // 获取用户所有角色ID
        Set<UUID> roleIds = userService.getUserRoleIds(currentUser.getId());

        // 从数据库获取用户可访问的菜单权限
        List<Permission> userPermissions = permissionRepository.findMenusByRoleIds(roleIds);
        // 将userPermissions转换为map,key为parentid,value为list<permission>，使用HashMap允许null键
        Map<UUID, List<Permission>> parentIdToPermissionsMap = userPermissions.stream()
                .filter(permission -> permission.getType() == 2) // 查找按钮权限
                .collect(Collectors.groupingBy(Permission::getParentId));

        // 过滤出菜单类型的权限（type=0：模块，type=1：页面）转换为menu对象
        // 优化：合并stream操作，减少中间集合创建，提高性能
        List<Menu> menuList = userPermissions.stream()
                .filter(permission -> permission.getType() == 0 || permission.getType() == 1)
                .sorted(Comparator.comparing(Permission::getSort, Comparator.nullsLast(Integer::compareTo)))
                .map(permission -> convertToMenu(permission, parentIdToPermissionsMap))
                .collect(Collectors.toList());
        // 将权限数据转换为菜单树结构
        return buildMenuTreeRecursive(menuList);
    }

    /**
     * 递归方式构建菜单树
     */
    public List<Menu> buildMenuTreeRecursive(List<Menu> menuList) {
        // 找出所有顶级菜单（parentId为null）
        List<Menu> rootMenus = menuList.stream()
                .filter(menu -> menu.getParentId() == null)
                .sorted(Comparator.comparing(Menu::getSort, Comparator.nullsLast(Integer::compareTo)))
                .collect(Collectors.toList());

        // 为每个顶级菜单递归构建子树
        for (Menu rootMenu : rootMenus) {
            buildChildren(rootMenu, menuList);
        }

        return rootMenus;
    }

    /**
     * 递归构建子菜单
     */
    private void buildChildren(Menu parentMenu, List<Menu> allMenus) {
        List<Menu> children = allMenus.stream()
                .filter(menu -> Objects.equals(menu.getParentId(), parentMenu.getId()))
                .sorted(Comparator.comparing(Menu::getSort, Comparator.nullsLast(Integer::compareTo)))
                .collect(Collectors.toList());

        parentMenu.setChildren(children);

        // 递归处理每个子菜单
        for (Menu child : children) {
            buildChildren(child, allMenus);
        }
    }

    /**
     * 将Permission对象转换为Menu对象，包含动态按钮权限
     * 
     * @param permission 权限对象
     * @param roleIds    用户角色ID集合，用于查询动态按钮权限
     * @return Menu对象
     */
    private Menu convertToMenu(Permission permission, Map<UUID, List<Permission>> parentIdToPermissionsMap) {
        Menu menu = new Menu();
        menu.setId(permission.getId());
        menu.setName(permission.getName());

        // 设置路径
        String path = permission.getHref();
        if (permission.getType() == 0) { // 模块类型
            menu.setPath("/" + path);
            menu.setComponent("RoutesAlias.Layout");
        } else if (permission.getType() == 1) { // 页面类型
            menu.setPath(path);
            // 使用component字段设置组件路径，与TypeScript接口保持一致
            menu.setComponent(permission.getComponent() != null ? permission.getComponent() : permission.getHref());
        }
        menu.setSort(permission.getSort());
        menu.setType(permission.getType()); // 转换为前端需要的类型
        menu.setIcon(permission.getIcon() != null ? permission.getIcon() : "");
        menu.setParentId(permission.getParentId());

        // 设置meta属性，严格按照TypeScript接口规范
        Map<String, Object> meta = new HashMap<>();
        // 使用title字段作为路由标题，与TypeScript接口保持一致
        meta.put("title", permission.getTitle() != null ? permission.getTitle() : permission.getName());

        // 设置图标
        if (permission.getIcon() != null && !permission.getIcon().isEmpty()) {
            meta.put("icon", permission.getIcon());
        }

        // 设置徽标相关属性
        if (permission.getShowBadge() != null) {
            meta.put("showBadge", permission.getShowBadge());
        }
        if (permission.getShowTextBadge() != null) {
            meta.put("showTextBadge", permission.getShowTextBadge());
        }

        // 设置隐藏相关属性
        if (permission.getHide() != null) {
            meta.put("isHide", permission.getHide());
        }
        if (permission.getHideTab() != null) {
            meta.put("isHideTab", permission.getHideTab());
        }

        // 设置链接和iframe属性
        if (permission.getLink() != null && !permission.getLink().isEmpty()) {
            meta.put("link", permission.getLink());
        }
        if (permission.getIframe() != null) {
            meta.put("isIframe", permission.getIframe());
        }

        // 设置缓存属性
        meta.put("keepAlive", permission.getKeepAlive());
        // 设置是否启用
        meta.put("isEnable", permission.getEnable() == 1);
        // 设置固定标签
        meta.put("fixedTab", permission.getFixedTab());
        // 设置权限
        meta.put("label", permission.getPermission());
        // 设置激活路径
        meta.put("activePath", permission.getActivePath());
        // 按钮权限（type=2）
        if (permission.getType() == 1) { // 仅对页面类型添加按钮权限
            List<Permission> buttonPermissions = parentIdToPermissionsMap.getOrDefault(permission.getId(),
                    Collections.emptyList());

            if (!buttonPermissions.isEmpty()) {
                List<Map<String, String>> authList = buttonPermissions.stream()
                        .map(buttonPermission -> {
                            Map<String, String> auth = new HashMap<>();
                            auth.put("id", buttonPermission.getId().toString());
                            auth.put("title", buttonPermission.getTitle() != null ? buttonPermission.getTitle()
                                    : buttonPermission.getName());
                            String sort = buttonPermission.getSort() != null ? buttonPermission.getSort().toString()
                                    : "";
                            auth.put("sort", sort);
                            String icon = buttonPermission.getIcon() != null ? buttonPermission.getIcon() : "";
                            auth.put("icon", icon);
                            String authMark = buttonPermission.getPermission();

                            auth.put("authMark", authMark);
                            return auth;
                        })
                        .collect(Collectors.toList());

                meta.put("authList", authList);
            }
        }

        menu.setMeta(meta);
        return menu;
    }

}